package ntd.util.frame.task.handle.data;

import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.StaticLog;
import ntd.action.ActionManager;
import ntd.action.bo.ActionInBo;
import ntd.action.bo.ActionInfo;
import ntd.task.Task;
import ntd.task.bo.TaskInfo;
import ntd.util.config.common.bo.RequestInfo;
import ntd.util.config.common.enums.EnumDataRule;
import ntd.util.config.common.enums.EnumLogic;
import ntd.util.frame.data.factory.FactoryData;
import ntd.util.frame.data.tool.ToolMysql;
import ntd.util.frame.task.handle.data.listen.DataListen;
import ntd.util.util.ToolDuration;

import javax.sql.DataSource;
import java.util.List;

public class TaskDataTrigger implements Task {

    private Db db;
    private ToolMysql toolMysql;

    @Override
    public TaskInfo info() {
        return new TaskInfo("任务-数据触发器执行任务", "task-data-trigger-exec", new TaskDataTrigger());
    }

    @Override
    public void execute(Object o) {
        ToolDuration.duration(() -> {
            // 初始化数据源
            DataSource dataSource = FactoryData.dataSource();
            db = Db.use(dataSource);
            toolMysql = new ToolMysql(dataSource);
            // 查询触发器列表
            List<Entity> all = db.findAll(new Entity("data_trigger"));
            // 遍历触发器
            for (Entity entity : all) {
                // 执行触发器
                exec(entity);
            }
        }, "任务触发器执行");
    }

    /**
     * 执行触发器
     *
     * @param entity
     */
    private void exec(Entity entity) {
        // 获取触发器条件
        String extendJson = entity.getStr("extend_json");
        // 判定触发器规则为空直接返回
        if (StrUtil.isBlank(extendJson) || !JSONUtil.isTypeJSON(extendJson)) {
            return;
        }
        JSONObject ruleJson = JSONUtil.parseObj(extendJson);
        JSONArray triggerArr = ruleJson.getJSONArray("triggerArr");
        JSONArray execArr = ruleJson.getJSONArray("exceArr");
        // 判定是否符合条件
        if (isTrigger(triggerArr)) {
            // 符合条件执行-执行器
            execAction(execArr);
        }
    }

    /**
     * 执行器
     * @param execArr
     */
    private void execAction(JSONArray execArr) {
        for (int i = 0; i < execArr.size(); i++) {
            JSONObject jsonObject = execArr.getJSONObject(i);
            String action = jsonObject.getStr("action");
            String deviceId = jsonObject.getStr("deviceId");
            ActionInfo actionInfo = ActionManager.get(action);
            StaticLog.info("触发器动作[{}]执行 - {}", action,deviceId);
            actionInfo.getAction().execute(new ActionInBo().setDataCode(deviceId));
        }
    }

    /**
     * 判定条件是否符合
     * @param triggerArr
     * @return
     */
    private boolean isTrigger(JSONArray triggerArr) {
        boolean compare = false;

        for (int i = 0; i < triggerArr.size(); i++) {
            JSONObject jsonObject = triggerArr.getJSONObject(i);

            // 监听器id
            String listenDataId = jsonObject.getStr("listenDataId");
            // 获取侦听数据
            JSONObject dataByListenId = DataListen.getDataByListenId(listenDataId);

            // 比对数据标识
            String listenDataKey = jsonObject.getStr("listenDataKey");
            // 比对规则
            String listenDataRule = jsonObject.getStr("listenDataRule");
            // 比对值
            String listenDataVal = jsonObject.getStr("listenDataVal");

            // 连接规则
            String triggerLogic = jsonObject.getStr("triggerLogic");

            String dataVal = dataByListenId.getStr(listenDataKey);

            boolean newCompare = EnumDataRule.val(listenDataRule).compare(dataVal, listenDataVal);

            StaticLog.info("规则比对[{}] 规则值[{}] -{}- 数据值[{}]", listenDataKey, listenDataVal, listenDataRule, dataVal);

            if (StrUtil.isBlank(triggerLogic)) {
                compare = newCompare;
            } else {
                EnumLogic val = EnumLogic.val(triggerLogic);
                // 与关系
                if (EnumLogic.AND.equals(val)) {
                    compare = newCompare && compare;
                }
                // 或关系
                if (EnumLogic.OR.equals(val)) {
                    compare = newCompare || compare;
                }
            }
        }

        return compare;
    }

    public static void main(String[] args) {
        TaskDataTrigger taskDataTrigger = new TaskDataTrigger();
        taskDataTrigger.execute(null);
    }
}
